GOHOSTOS:=$(shell go env GOHOSTOS)
APP_NAME=$(ROOT_PACKAGE)

ifeq ($(GOHOSTOS), windows)
	#the `find.exe` is different from `find` in bash/shell.
	#to see https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/find.
	#changed to use git-bash.exe to run find cli or other cli friendly, caused of every developer has a Git.
	#Git_Bash= $(subst cmd\,bin\bash.exe,$(dir $(shell where git)))
	Git_Bash=$(subst \,/,$(subst cmd\,bin\bash.exe,$(dir $(shell where git | grep cmd))))
	INTERNAL_PROTO_FILES=$(shell $(Git_Bash) -c "find app/$(APP_NAME)/internal -name *.proto")
	API_PROTO_FILES=$(shell $(Git_Bash) -c "find api/$(APP_NAME) -name *.proto")
else
	INTERNAL_PROTO_FILES=$(shell find app/$(APP_NAME)/internal -name *.proto)
	API_PROTO_FILES=$(shell find api/$(APP_NAME) -name *.proto)
endif

# init: init env
.PHONY: init
init:
	go install google.golang.org/protobuf/cmd/protoc-gen-go@latest
	go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@latest
	go install github.com/go-kratos/kratos/cmd/kratos/v2@latest
	go install github.com/go-kratos/kratos/cmd/protoc-gen-go-http/v2@latest
	go install github.com/google/gnostic/cmd/protoc-gen-openapi@latest
	go install github.com/google/wire/cmd/wire@latest

# config: generate internal proto
.PHONY: config
config:
	protoc --proto_path=./app/$(APP_NAME)/internal \
	       --proto_path=./third_party \
 	       --go_out=paths=source_relative:./app/$(APP_NAME)/internal \
	       $(INTERNAL_PROTO_FILES)

# api: generate api proto
.PHONY: api
api:
	protoc --proto_path=./api/$(APP_NAME) \
	       --proto_path=./third_party \
 	       --go_out=paths=source_relative:./api/$(APP_NAME) \
 	       --go-http_out=paths=source_relative:./api/$(APP_NAME) \
 	       --go-grpc_out=paths=source_relative:./api/$(APP_NAME) \
	       --openapi_out=naming=proto,fq_schema_naming=true,default_response=false:./app/$(APP_NAME) \
	       $(API_PROTO_FILES)

# proto: generate internal proto struct
.PHONY: proto
proto:
	protoc --proto_path=./api/$(APP_NAME) \
			--proto_path=./third_party \
			--go_out=paths=source_relative:./api/$(APP_NAME) \
			$(API_PROTO_FILES)

# http: generate http code
.PHONY: http
http:
	protoc --proto_path=./api/$(APP_NAME) \
			--proto_path=./third_party \
			--go_out=paths=source_relative:./api \
			--go-http_out=paths=source_relative:./api/$(APP_NAME) \
			--openapi_out=fq_schema_naming=true,default_response=false:./app/$(APP_NAME) \
			$(API_PROTO_FILES)

# grpc: generate grpc code
.PHONY: grpc
grpc:
	protoc --proto_path=./api/$(APP_NAME) \
			--proto_path=./third_party \
			--go_out=paths=source_relative:./api/$(APP_NAME) \
			--go-grpc_out=paths=source_relative:./api/$(APP_NAME) \
			$(API_PROTO_FILES)

# generate errors code
.PHONY: errors
errors:
	protoc --proto_path=./api/$(APP_NAME) \
          --proto_path=./third_party \
          --go_out=paths=source_relative:./api/$(APP_NAME) \
          --go-errors_out=paths=source_relative:./api/$(APP_NAME) \
          $(API_PROTO_FILES)

# generate validate proto
.PHONY: validate
validate:
	protoc --proto_path=./api/$(APP_NAME) \
			--proto_path=./third_party \
			--go_out=paths=source_relative:./api/$(APP_NAME) \
			--validate_out=paths=source_relative,lang=go:./api/$(APP_NAME) \
			$(API_PROTO_FILES)

# docs: generate docs file
.PHONY: docs
docs:
	@mkdir -p ./docs/$(APP_NAME)
	protoc --proto_path=./api/$(APP_NAME) \
			--proto_path=./third_party \
			--go_out=paths=source_relative:./api/$(APP_NAME) \
			--doc_out=./docs/$(APP_NAME) \
			--doc_opt=html,index.html \
			$(API_PROTO_FILES)

# swagger: generate swagger file
.PHONY: swagger
swagger:
	@mkdir -p ./docs/swagger/$(APP_NAME)
	protoc --proto_path=./api/$(APP_NAME) \
	        --proto_path=./third_party \
	        --openapiv2_out ./docs/swagger/$(APP_NAME) \
	        --openapiv2_opt logtostderr=true \
           $(API_PROTO_FILES)
	@kratos-ext swagger bearer -t ./docs/swagger/$(APP_NAME)

# wire: wire
.PHONY: wire
wire:
	cd app/$(APP_NAME)/cmd/$(APP_NAME) && wire

# genproto: generate proto template
.PHONY: genproto.%
genproto.%:
	kratos proto add api/$(APP_NAME)/v1/$*.proto

# generrcode: generate error code
.PHONY: generrcode.%
generrcode.%:
	kratos-ext proto errcode api/$(APP_NAME)/v1/error_reason.proto -s $*

# genservice: generate service code
.PHONY: genservice.%
genservice.%:
	kratos-ext proto server api/$(APP_NAME)/v1/$*.proto -t app/$(APP_NAME)/internal/service

# genbiz: generate biz code
.PHONY: genbiz.%
genbiz.%:
	kratos-ext proto biz api/$(APP_NAME)/v1/$*.proto -t app/$(APP_NAME)/internal/biz

# genrepo: generate repo code
.PHONY: genrepo.%
genrepo.%:
	kratos-ext proto repo api/$(APP_NAME)/v1/$*.proto -t app/$(APP_NAME)/internal/data

# gencode: generate all code
.PHONY: gencode.%
gencode.%:
	@$(MAKE) generrcode.$*
	@$(MAKE) errors
	@$(MAKE) api
	@$(MAKE) validate
	@$(MAKE) genservice.$*
	@$(MAKE) genbiz.$*
	@$(MAKE) genrepo.$*
	@$(MAKE) wire
	@$(MAKE) format
	@$(MAKE) lint

# gencode: generate api code
.PHONY: genapi
genapi: 
	@$(MAKE) errors
	@$(MAKE) api
	@$(MAKE) validate
	@$(MAKE) wire
	@$(MAKE) format
	@$(MAKE) lint